package app.common.utils.dingtalk;

import com.alibaba.fastjson.JSON;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiEduClassStudentinfoGetRequest;
import com.dingtalk.api.request.OapiEduDeptGetRequest;
import com.dingtalk.api.request.OapiEduDeptListRequest;
import com.dingtalk.api.request.OapiEduUserGetRequest;
import com.dingtalk.api.request.OapiEduUserListRequest;
import com.dingtalk.api.request.OapiEduUserRelationGetRequest;
import com.dingtalk.api.response.OapiEduClassStudentinfoGetResponse;
import com.dingtalk.api.response.OapiEduDeptGetResponse;
import com.dingtalk.api.response.OapiEduDeptListResponse;
import com.dingtalk.api.response.OapiEduUserGetResponse;
import com.dingtalk.api.response.OapiEduUserListResponse;
import com.dingtalk.api.response.OapiEduUserRelationGetResponse;
import com.taobao.api.ApiException;

import java.util.ArrayList;
import java.util.List;

/**
 * <b>教育模块钉钉api工具类</b>
 * <p>
 *     <a href="https://open.dingtalk.com/document/isvapp/overview-6">服务端API>行业开放>新教育>概述</a>
 * </p>
 * @author feizns
 * @since 2023/2/14
 */
public class EduUtils {

    /**
     * {@link Auth2Utils}
     */
    private final Auth2Utils auth2Utils;

    public EduUtils(Auth2Utils auth2Utils) {
        this.auth2Utils = auth2Utils;
    }

    /**
     * <b>获取部门列表</b>
     * @link <a href="https://open.dingtalk.com/document/isvapp/obtains-the-department-node-list">获取部门列表</a>
     * @param superId 父部门的节点ID，如果不填，则默认获取第一层级的部门的节点。
     * @return {@link OapiEduDeptListResponse.OpenEduDeptDetails}
     */
    public List<OapiEduDeptListResponse.OpenEduDeptDetails> deptList(Long superId) throws ApiException {
        List<OapiEduDeptListResponse.OpenEduDeptDetails> resultList = new ArrayList<>();
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/dept/list");
        final long maxPageSize = 30L;
        long pageNo = 1L;
        OapiEduDeptListResponse.OpenEduDeptListResponse result;
        do {
            OapiEduDeptListRequest req = new OapiEduDeptListRequest();
            req.setPageSize(maxPageSize);
            req.setPageNo(pageNo);
            if ( superId != null )
                req.setSuperId(superId);
            OapiEduDeptListResponse rsp = client.execute(req, auth2Utils.getAccessToken());
            if ( !rsp.isSuccess() )
                throw new RuntimeException(JSON.toJSONString(rsp));
            result = rsp.getResult();
            pageNo++;
            resultList.addAll(result.getDetails());
        } while ( result.getHasMore() );
        return resultList;
    }

    /**
     * <b>获取部门详情</b>
     * @link <a href="https://open.dingtalk.com/document/isvapp/obtains-queries-department-details">获取部门详情</a>
     * @param deptId 部门编号
     * @return {@link OapiEduDeptGetResponse.OpenEduDeptDetail}
     */
    public OapiEduDeptGetResponse.OpenEduDeptDetail deptGet(Long deptId) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/dept/get");
        OapiEduDeptGetRequest req = new OapiEduDeptGetRequest();
        req.setDeptId(deptId);
        OapiEduDeptGetResponse resp = client.execute(req, auth2Utils.getAccessToken());
        if ( !resp.isSuccess() )
            throw new RuntimeException(JSON.toJSONString(resp));
        return resp.getResult().getDetail();
    }

    /**
     * <b>获取人员列表</b>
     * @link <a href="https://open.dingtalk.com/document/isvapp/obtains-a-list-of-home-school-user-identities">获取人员列表</a>
     * @param classId 班级编号 班级ID。
     * 企业内部应用，调用获取部门列表接口获取dept_type为class时的dept_id参数值。
     * 第三方企业应用，调用获取部门列表接口获取dept_type为class时的dept_id参数值。
     * @param role 角色 家校人员角色。
     * teacher：老师
     * guardian：监护人
     * student：学生
     * @return {@link OapiEduUserListResponse.OpenEduUserDetail}
     */
    public List<OapiEduUserListResponse.OpenEduUserDetail> deptUserList(Long classId, EduUserRole role) throws ApiException {
        List<OapiEduUserListResponse.OpenEduUserDetail> resultList = new ArrayList<>();
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/user/list");
        final long maxPageSize = 30L;
        long pageNo = 1L;
        OapiEduUserListResponse.Result result;
        do {
            OapiEduUserListRequest req = new OapiEduUserListRequest();
            req.setPageSize(maxPageSize);
            req.setPageNo(pageNo);
            req.setRole(role.name());
            req.setClassId(classId);
            OapiEduUserListResponse rsp = client.execute(req, auth2Utils.getAccessToken());
            if ( !rsp.isSuccess() )
                throw new RuntimeException(JSON.toJSONString(rsp));
            result = rsp.getResult();
            pageNo++;
            resultList.addAll(result.getDetails());
        } while (result.getHasMore());
        return resultList;
    }

    /**
     * 教育角色
     */
    public enum EduUserRole {
        /**
         * 老师
         */
        teacher,
        /**
         * 监护人
         */
        guardian,
        /**
         * 学生
         */
        student
    }


    /**
     * 获取学生详情信息
     * @param classId 班级编号
     * @param studentUserid 学生编号
     * @return {@link OapiEduClassStudentinfoGetResponse.OpenStudentSelectDto}
     */
    public OapiEduClassStudentinfoGetResponse.OpenStudentSelectDto getStudentInfo(Long classId, String studentUserid) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/class/studentinfo/get");
        OapiEduClassStudentinfoGetRequest req = new OapiEduClassStudentinfoGetRequest();
        req.setAppId(auth2Utils.getConfig().getAgentId());
        req.setClassId(classId);
        req.setUserid(studentUserid);
        OapiEduClassStudentinfoGetResponse rsp;
        try {
            rsp = client.execute(req, auth2Utils.getAccessToken());
            if ( !rsp.isSuccess() )
                throw new RuntimeException(rsp.getBody());

            return rsp.getResult();
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * <b>获取学生监护人详情</b>
     * @link <a href="https://open.dingtalk.com/document/isvapp/obtain-the-relationship-between-home-and-school-personnel">获取学生监护人详情</a>
     * @param classId 班级编号
     * @param fromUserid 家长编号
     * @return {@link OapiEduUserRelationGetResponse.Result}
     */
    public OapiEduUserRelationGetResponse.Result eduUserRelationGet(Long classId, String fromUserid) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/user/relation/get");
        OapiEduUserRelationGetRequest req = new OapiEduUserRelationGetRequest();
        req.setFromUserid(fromUserid);
        req.setClassId(classId);
        OapiEduUserRelationGetResponse rsp;
        try {
            rsp = client.execute(req, auth2Utils.getAccessToken());
            if ( !rsp.isSuccess() )
                throw new RuntimeException(rsp.getBody());
            return rsp.getResult();
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * <b>获取用户详情</b>
     * @param classId 班级编号
     * @param role {@link EduUserRole}
     * @param userid 用户编号
     * @return {@link OapiEduUserGetResponse}
     */
    public OapiEduUserGetResponse.Result eduUserGet(Long classId, EduUserRole role, String userid) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/edu/user/get");
        OapiEduUserGetRequest req = new OapiEduUserGetRequest();
        req.setClassId(classId);
        req.setRole(role.name());
        req.setUserid(userid);
        OapiEduUserGetResponse rsp = null;
        try {
            rsp = client.execute(req, auth2Utils.getAccessToken());
            if ( !rsp.isSuccess() )
                throw new RuntimeException(rsp.getBody());
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
        return rsp.getResult();
    }

}
